package com.core.tag;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.jsp.JspWriter;

import org.springframework.web.servlet.tags.RequestContextAwareTag;

import com.core.dao.CommonDAO;
import com.core.dao.EnumItemDAO;
import com.core.model.EnumItem;
import com.core.util.StringUtils;

/**
 * 字典标签 不仅包含枚举表的下拉列表
 * 
 * 支持查询具体的表 控件类型包含input label select
 * 
 * @author pt-chenqw
 * 
 */
@SuppressWarnings("unchecked")
public class DictTag extends RequestContextAwareTag {

	private static final long serialVersionUID = 1L;
	
	private EnumItemDAO enumItemDAO;
	
	private CommonDAO commonDAO;

	/** class属性 */
	private String className;

	/** name属性 */
	private String name;

	/** id属性 */
	private String id;

	/** 要查询的表名 */
	private String tableName;

	/** 下拉列表显示的字段名称 */
	private String fieldName;

	/** 下拉列表未显示的字段名称 */
	private String fieldValue;

	/** 具体的值 */
	private String value;

	/** 控件类型:input label select */
	private String type;

	/** 要查询的枚举关键字 */
	private String dictCode;
	
	/**是否只读*/
	private String readOnly;
	
	/**文本提示*/
	private String placeholder;
	
	/**是否可为空*/
	private String empty;
	
	/**过滤字段*/
	private String filter;
	
	@Override
	protected int doStartTagInternal() throws Exception {
		JspWriter out = pageContext.getOut();
		commonDAO = (CommonDAO) this.getRequestContext().getWebApplicationContext().getBean("commonDAO");
		enumItemDAO = this.getRequestContext().getWebApplicationContext().getBean(EnumItemDAO.class);
		StringBuffer stringBuffer = new StringBuffer();
		if("select".equals(type)){
			stringBuffer = select(stringBuffer);
		}else if("hidden".equals(type)){
			stringBuffer.append("<input type='hidden' value='"+ value +"'>");
		}else{
			EnumItem enumItem = null;
			Object object = null;
			if(StringUtils.notEmpty(value)){
				if(StringUtils.notEmpty(dictCode)){
					enumItem = enumItemDAO.getEnumItemByEnumWordAndCode(dictCode, value);
				}
				if(StringUtils.notEmpty(fieldValue) && StringUtils.notEmpty(tableName)){
					object = commonDAO.findOne("from " + tableName + " where " + fieldValue + "=?", value);
				}
			}
			if("text".equals(type)){
				stringBuffer = text(stringBuffer, enumItem, object);
			}
			if("label".equals(type)){
				stringBuffer = label(stringBuffer, enumItem, object);
			}
		}
		out.print(stringBuffer.toString());
		return 0;
	}
	
	/**
	 * 枚举下拉列表
	 * @param stringBuffer
	 * @return
	 */
	private StringBuffer getEnumList(StringBuffer stringBuffer){
		List<EnumItem> enumItems = enumItemDAO.getEnumItemByEnumword(dictCode);
		for (EnumItem enumItem : enumItems) {
			if(enumItem.getCode().equals(value)){
				stringBuffer.append("<option selected='selected' value='"+ enumItem.getCode() +"'>"+ enumItem.getName() +"</option>");
			}else{
				stringBuffer.append("<option value='"+ enumItem.getCode() +"'>"+ enumItem.getName() +"</option>");
			}
		}
		return stringBuffer;
	}
	
	/**
	 * 查询除枚举表之外的表信息
	 * @param stringBuffer
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	private StringBuffer getTableList(StringBuffer stringBuffer) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		Object[] objs = null;
		String hql = "from " + tableName;
		if(StringUtils.notEmpty(filter)){
			hql += " where "+ filter + "=?";
			objs = new Object[]{value};
		}
		List<Object> list = commonDAO.findByHQL(hql, objs);
		String filedNameMethod = "get" + StringUtils.capitalize(fieldName) + "()";
		String filedValueMethod = "get" + StringUtils.capitalize(fieldValue) + "()";
		for (Object object : list) {
			//获取类的方法
			Class<?> cla = object.getClass();
			Method[] methods = cla.getMethods();
			//将ID和name值保存在数组中,不能在循环中赋值的原因是method遍历的顺序不能确定
			Object[] obj = new Object[2];
			for (Method method : methods) {
				//id
				if(filedValueMethod.contains(method.getName())){
					obj[0] = method.invoke(object);
				}
				//name
				if(filedNameMethod.contains(method.getName())){
					obj[1] = method.invoke(object);
				}
			}
			stringBuffer.append("<option value='"+ obj[0] +"'");
			if(obj[0].toString().equals(value)){
				stringBuffer.append(" selected='selected'");
			}
			stringBuffer.append(">");
			stringBuffer.append(obj[1] +"</option>");
			
		}
		return stringBuffer;
	}
	
	/**
	 * 生成select标签
	 * @param stringBuffer
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	private StringBuffer select(StringBuffer stringBuffer) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		stringBuffer.append("<select name='"+ name +"' class='"+ className +"' ");
		if(StringUtils.notEmpty(id)){
			stringBuffer.append("id='"+ id +"' ");
		}
		//不可为空则加上必输校验,此处的校验没有提示
		if("false".equals(empty)){
			stringBuffer.append("data-rule-required='true' data-msg-required=' '");
		}
		stringBuffer.append("><option value=''><label>请选择</label></option>");
		if(StringUtils.notEmpty(dictCode)){
			stringBuffer = getEnumList(stringBuffer);
		}
		if(StringUtils.notEmpty(tableName)){
			stringBuffer = getTableList(stringBuffer);
		}
		stringBuffer.append("</select>");
		return stringBuffer;
	}
	
	/**
	 * 生成input标签
	 * @param stringBuffer
	 * @throws InvocationTargetException 
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 */
	private StringBuffer text(StringBuffer stringBuffer,EnumItem enumItem,Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		stringBuffer.append("<input  type='text' name='"+ name +"' class='"+ className +"' ");
		stringBuffer.append("id='"+ id +"' ");
		if(enumItem != null){
			stringBuffer.append("value='"+ enumItem.getName() +"'");
		}
		if(object != null){
			stringBuffer.append("value='"+ getObjectByReflect(object) +"'");
		}
		if("true".equals(readOnly)){
			stringBuffer.append("readonly='readonly'");
		}
		stringBuffer.append("/>");
		return stringBuffer;
	}
	
	/**
	 * 反射获取方法值
	 * @param object
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	private Object getObjectByReflect(Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		String fieldNameMethod = "get" + StringUtils.capitalize(this.fieldName) + "()";
		Class<?> clazz = object.getClass();
		Method[] methods = clazz.getMethods();
		for (Method method : methods) {
			if(fieldNameMethod.contains(method.getName())){
				return method.invoke(object);
			}
		}
		return null;
	}
	
	/**
	 * 获取label标签
	 * @param stringBuffer
	 * @param enumItem
	 * @param object
	 * @return
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	private StringBuffer label(StringBuffer stringBuffer,EnumItem enumItem,Object object) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		if(enumItem != null){
			stringBuffer.append(enumItem.getName());
		}
		if(object != null){
			stringBuffer.append(getObjectByReflect(object));
		}
		return stringBuffer;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public String getFieldName() {
		return fieldName;
	}

	public void setFieldName(String fieldName) {
		this.fieldName = fieldName;
	}

	public String getFieldValue() {
		return fieldValue;
	}

	public void setFieldValue(String fieldValue) {
		this.fieldValue = fieldValue;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getDictCode() {
		return dictCode;
	}

	public void setDictCode(String dictCode) {
		this.dictCode = dictCode;
	}

	public String getReadOnly() {
		return readOnly;
	}

	public void setReadOnly(String readOnly) {
		this.readOnly = readOnly;
	}

	public String getPlaceholder() {
		return placeholder;
	}

	public void setPlaceholder(String placeholder) {
		this.placeholder = placeholder;
	}

	public String getEmpty() {
		return empty;
	}

	public void setEmpty(String empty) {
		this.empty = empty;
	}

	public String getFilter() {
		return filter;
	}

	public void setFilter(String filter) {
		this.filter = filter;
	}
	
}
